In [ ]:
import numpy as np
import sympy as sym
import solowpy

1 Creating an instance of the solow.Model class

In this notebook I will walk you through the creation of an instance of the solow.Model class. To create an instance of the solow.Model we must define two primitives: an aggregate production function and a dictionary of model parameter values.

1.1 Defining the production function $F$:

At each point in time the economy in a Solow growth model has some amounts of capital, $K$, labor, $L$, and knowledge (or technology), $A$, that can be combined to produce output, $Y$, according to some function, $F$:

$$ Y(t) = F(K(t), A(t)L(t)) \tag{1.1.1} $$

where $t$ denotes time. Note that $A$ and $L$ are assumed to enter multiplicatively. Typically $A(t)L(t)$ denotes "effective labor", and technology that enters in this fashion is known as labor-augmenting or "Harrod neutral."

A key assumption of the model is that the function $F$ exhibits constant returns to scale in capital and labor inputs. Specifically,

$$ F(cK(t), cA(t)L(t)) = cF(K(t), A(t)L(t)) = cY(t) \tag {1.1.2} $$

for any $c \ge 0$. For reference, the above information is contained in the docstring of the solow.Model.output attribute.


In [ ]:
solow.Model.output?

Examples:

A common functional form for aggregate production in a Solow model that satisies the above assumptions is the Cobb-Douglas production function

\begin{equation} \lim_{\rho \rightarrow 0} Y(t) = K(t)^{\alpha}(A(t)L(t))^{1-\alpha}. \tag{1.1.3} \end{equation}

The Cobb-Douglas production function is actually a special case of a more general class of production functions called constant elasticity of substitution (CES) production functions.

\begin{equation} Y(t) = \bigg[\alpha K(t)^{\rho} + (1-\alpha) (A(t)L(t))^{\rho}\bigg]^{\frac{1}{\rho}} \tag{1.1.4} \end{equation}

where $0 < \alpha < 1$ and $-\infty < \rho < 1$. The parameter $\rho = \frac{\sigma - 1}{\sigma}$ where $\sigma$ is the elasticity of substitution between factors of production. Taking the limit of equation 1.2 as the elasticity of subsitution goes to unity (i.e., $\sigma=1 \implies \rho=0$) recovers the Cobb-Douglas functional form.


In [ ]:
# define model variables
A, K, L = sym.symbols('A, K, L')

# define production parameters
alpha, sigma = sym.symbols('alpha, sigma')

# define a production function
cobb_douglas_output = K**alpha * (A * L)**(1 - alpha)

rho = (sigma - 1) / sigma
ces_output = (alpha * K**rho + (1 - alpha) * (A * L)**rho)**(1 / rho)

1.2 Defining model parameters

A generic Solow growth model has several parameters that need to be specified. To see which parameters are required, we can check the docstring of the solow.Model.params attribute.


In [ ]:
solow.Model.params?

In addition to the standard parameters $g, n, s, \delta$, one will also need to specify any required parameters for the production function. In order to make sure that parameter values are consistent with the models assumptions some basic validation of the solow.Model.params attribute is done when ever the attribute is set.


In [ ]:
# these parameters look fishy...why?
default_params = {'A0': 1.0, 'L0': 1.0, 'g': 0.0, 'n': -0.03, 's': 0.15,
                  'delta': 0.01, 'alpha': 0.33}

In [ ]:
# ...raises an AttributeError
model = solowpy.Model(output=cobb_douglas_output, params=default_params)

Examples:

Here are some examples of how one successfully creates an instance of the solow.Model class...


In [ ]:
cobb_douglas_params = {'A0': 1.0, 'L0': 1.0, 'g': 0.02, 'n': 0.03, 's': 0.15,
                       'delta': 0.05, 'alpha': 0.33}

cobb_douglas_model = solow.Model(output=cobb_douglas_output,
                                 params=cobb_douglas_params)

In [ ]:
ces_params = {'A0': 1.0, 'L0': 1.0, 'g': 0.02, 'n': 0.03, 's': 0.15,
              'delta': 0.05, 'alpha': 0.33, 'sigma': 0.95}

ces_model = solowpy.Model(output=ces_output, params=ces_params)

1.3 Other attributes of the solow.Model class

The intensive form of the production function

The assumption of constant returns to scale allows us to work with the intensive form of the aggregate production function, $F$. Defining $c=1/AL$ one can write

$$ F\bigg(\frac{K}{AL}, 1\bigg) = \frac{1}{AL}F(A, K, L) \tag{1.3.1} $$

Defining $k=K/AL$ and $y=Y/AL$ to be capital per unit effective labor and output per unit effective labor, respectively, the intensive form of the production function can be written as

$$ y = f(k). \tag{1.3.2}$$

Additional assumptions are that $f$ satisfies $f(0)=0$, is concave (i.e., $f'(k) > 0, f''(k) < 0$), and satisfies the Inada conditions: $\lim_{k \rightarrow 0} = \infty$ and $\lim_{k \rightarrow \infty} = 0$. The (Inada, 1964) conditions are sufficient (but not necessary!) to ensure that the time path of capital per effective worker does not explode. Much of the above information is actually taken straight from the docstring for the solow.Model.intensive_output attribute.


In [ ]:
solowpy.Model.intensive_output?

In [ ]:
ces_model.intensive_output

One can numerically evaluate the intensive output for various values of capital stock (per unit effective labor) as follows...


In [ ]:
ces_model.evaluate_intensive_output(np.linspace(1.0, 10.0, 25))

The marginal product of capital

The marginal product of capital is defined as follows:

$$ \frac{\partial F(K, AL)}{\partial K} \equiv f'(k) \tag{1.3.3}$$

where $k=K/AL$ is capital stock (per unit effective labor).


In [ ]:
solowpy.Model.marginal_product_capital?

In [ ]:
ces_model.marginal_product_capital

One can numerically evaluate the marginal product of capital for various values of capital stock (per unit effective labor) as follows...


In [ ]:
ces_model.evaluate_mpk(np.linspace(1.0, 10.0, 25))

Equation of motion for capital (per unit effective labor)

Because the economy is growing over time due to technological progress, $g$, and population growth, $n$, it makes sense to focus on the capital stock per unit effective labor, $k$, rather than aggregate physical capital, $K$. Since, by definition, $k=K/AL$, we can apply the chain rule to the time derative of $k$.

\begin{align} \dot{k}(t) =& \frac{\dot{K}(t)}{A(t)L(t)} - \frac{K(t)}{[A(t)L(t)]^2}\bigg[\dot{A}(t)L(t) + \dot{L}(t)A(t)\bigg] \\ =& \frac{\dot{K}(t)}{A(t)L(t)} - \bigg(\frac{\dot{A}(t)}{A(t)} + \frac{\dot{L}(t)}{L(t)}\bigg)\frac{K(t)}{A(t)L(t)} \tag{1.3.4} \end{align}

By definition, $k=K/AL$, and by assumption $\dot{A}/A$ and $\dot{L}/L$ are $g$ and $n$ respectively. Aggregate capital stock evolves according to

$$ \dot{K}(t) = sF(K(t), A(t)L(t)) - \delta K(t). \tag{1.3.5}$$

Substituting these facts into the above equation yields the equation of motion for capital stock (per unit effective labor).

\begin{align} \dot{k}(t) =& \frac{sF(K(t), A(t)L(t)) - \delta K(t)}{A(t)L(t)} - (g + n)k(t) \\ =& \frac{sY(t)}{A(t)L(t)} - (g + n + \delta)k(t) \\ =& sf(k(t)) - (g + n + \delta)k(t) \tag{1.3.6} \end{align}

The above information is available for reference in the docstring for the solow.Model.k_dot attribute.


In [ ]:
solowpy.Model.k_dot?

In [ ]:
ces_model.k_dot

One can numerically evaluate the equation of motion for capital (per unit effective labor) for various values of capital stock (per unit effective labor) as follows...


In [ ]:
ces_model.evaluate_k_dot(np.linspace(1.0, 10.0, 25))

1.4 Sub-classing the solow.Model class

Several commonly used functional forms for aggregate production, including both the Cobb-Douglas and Constant Elasticity of Substitution (CES) production functions, have been sub-classed from solow.Model. For these functional forms, one only needs to specify a valid dictionary of model parameters.


In [ ]:
solowpy.cobb_douglas?

In [ ]:
cobb_douglas_model = solowpy.CobbDouglasModel(params=cobb_douglas_params)

In [ ]:
solowpy.ces?

In [ ]:
ces_model = solowpy.CESModel(params=ces_params)

Now that you understand the basics, we can move on to finding the steady state of the Solow growth model.


In [ ]: